#!/bin/python
from vBaum import *
from math import *
from random import *
import queue
import _thread

#radius = 4
#inset = 2
#minvolume = 10000

def randVector(vector, amount):
    outVec=[]
    for x in vector :
        outVec.append((random() * 2.0 - 1.0)*amount + x)
    return outVec

def split_n_pieces(toSplit, n):
    minVolume = toSplit.countVoxels() / n
    returnQueue = queue.Queue()
    split_minvolumeThreaded(toSplit, minVolume, returnQueue)
    return returnQueue.get()
    # return split_minvolume(toSplit, minVolume)
    
def split_minvolume(toSplit, minvolume):
    voxelCount = toSplit.countVoxels()
    if voxelCount < minvolume: return [toSplit]
        
    #get major axis of object
    (objMin, objMax)=toSplit.getExtents();
    iAxis = 0
    objSize=objMax-objMin
    objCenter = toSplit.centerOfMass()

    objSizeList = [objSize.x, objSize.y, objSize.z]
    print("object size is " + str(objSizeList))
    iCurrMax = objSizeList[0]
    iCurrMin = objSizeList[0]
    iCurrAxis = 0
    for i in objSizeList :
        if i > iCurrMax :
            iCurrMax = i
            iAxis=iCurrAxis
        if i < iCurrMin :
            iCurrMin = i
        iCurrAxis+=1

    #calculate size for fractal noise object
    majorLength=objSizeList[iAxis]
        
    objSizeList.pop(iAxis)
    #get max of remaining axes
    #cutterExt = max (objSizeList[0], objSizeList[1], majorLength*0.6)
    cutterExpo = int(log (majorLength, 2) + 1)
    
    print("Generating fractal noise")
    splitObject = FractalNoise(cutterExpo, int(majorLength*0.1), 1.1, False)
    splitObject.setPosition(objCenter)

    orientVec = [0,0,0]
    if iAxis == 0 :
        orientVec = [0, 90, 0]
    if iAxis == 1 :
        orientVec = [90, 0, 0]

    orientVec=randVector(orientVec, 6)

    splitObject.setRotation(orientVec[0], orientVec[1], orientVec[2])
    print(str(splitObject.countVoxels()))
    #perform boolean operation with fractal noise
    subtracted = toSplit.subtract(splitObject)
    intersected = toSplit.intersect(splitObject)
    
    return split_minvolume(subtracted, minvolume) + split_minvolume(intersected, minvolume)
    
def split_minvolumeThreaded(toSplit, minvolume, returnQueue):
    voxelCount = toSplit.countVoxels()
    if voxelCount < minvolume:
        returnQueue.put([toSplit])
        return
        
    #get major axis of object
    (objMin, objMax)=toSplit.getExtents();
    iAxis = 0
    objSize=objMax-objMin
    objCenter = toSplit.centerOfMass()

    objSizeList = [objSize.x, objSize.y, objSize.z]
    print("object size is " + str(objSizeList))
    iCurrMax = objSizeList[0]
    iCurrMin = objSizeList[0]
    iCurrAxis = 0
    for i in objSizeList :
        if i > iCurrMax :
            iCurrMax = i
            iAxis=iCurrAxis
        if i < iCurrMin :
            iCurrMin = i
        iCurrAxis+=1

    #calculate size for fractal noise object
    majorLength=objSizeList[iAxis]
        
    objSizeList.pop(iAxis)
    #get max of remaining axes
    #cutterExt = max (objSizeList[0], objSizeList[1], majorLength*0.6)
    cutterExpo = int(log (majorLength, 2) + 1)
    
    print("Generating fractal noise")
    splitObject = FractalNoise(cutterExpo, int(majorLength*0.1), 1.1, False)
    splitObject.setPosition(objCenter)

    orientVec = [0,0,0]
    if iAxis == 0 :
        orientVec = [0, 90, 0]
    if iAxis == 1 :
        orientVec = [90, 0, 0]

    orientVec=randVector(orientVec, 6)

    splitObject.setRotation(orientVec[0], orientVec[1], orientVec[2])
    print(str(splitObject.countVoxels()))
    #perform boolean operation with fractal noise
    subtracted = toSplit.subtract(splitObject)
    intersected = toSplit.intersect(splitObject)
    
    subQueue = queue.Queue()
    _thread.start_new_thread(split_minvolumeThreaded, (subtracted, minvolume, subQueue))
    _thread.start_new_thread(split_minvolumeThreaded, (intersected, minvolume, subQueue))
    returnQueue.put(subQueue.get() + subQueue.get())

def splitOld(toSplit, minvolume):
    voxelCount = toSplit.countVoxels()
    if voxelCount < minvolume:
        if voxelCount >= minvolume*0.5:
            return toSplit.subtract(toSplit.surfels())
        else: return toSplit
        
    #get major axis of object
    (objMin, objMax)=toSplit.getExtents();
    iAxis = 0
    objSize=objMax-objMin
    objCenter = toSplit.centerOfMass()

    objSizeList = [objSize.x, objSize.y, objSize.z]
    print("object size is " + str(objSizeList))
    iCurrMax = objSizeList[0]
    iCurrMin = objSizeList[0]
    iCurrAxis = 0
    for i in objSizeList :
        if i > iCurrMax :
            iCurrMax = i
            iAxis=iCurrAxis
        if i < iCurrMin :
            iCurrMin = i
        iCurrAxis+=1
#    print "selected split axis", iAxis
    #calculate size for fractal noise object
    majorLength=objSizeList[iAxis]
        
    objSizeList.pop(iAxis)
    #get max of remaining axes
    #cutterExt = max (objSizeList[0], objSizeList[1], majorLength*0.6)
    cutterExpo = int(log (majorLength, 2) + 1)
    
    splitObject = FractalNoise(cutterExpo, int(majorLength*0.1), 1.1, False)    
    splitObject.setPosition(objCenter)

    orientVec = [0,0,0]
    if iAxis == 0 :
        orientVec = [0, 90, 0]
    if iAxis == 1 :
        orientVec = [90, 0, 0]

    orientVec=randVector(orientVec, 6)

    splitObject.setRotation(orientVec[0], orientVec[1], orientVec[2])

    #perform boolean operation with fractal noise
    subtracted = toSplit.subtract(splitObject)
    lresult = split(subtracted, minvolume)
    
    intersected = toSplit.intersect(splitObject)
    rresult = split(intersected, minvolume)
    
    return lresult.union(rresult)
